package com.test.platform.service.common;

import com.test.platform.dao.*;
import com.test.platform.model.*;
import com.test.platform.service.developer.GitCodePRService;
import com.test.platform.service.publish.GitCodeCommitService;
import com.test.platform.service.Project.ProjectService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class DataInitService implements CommandLineRunner {
    
    @Autowired
    private GitCodePRService gitCodePRService;
    
    @Autowired
    private GitCodeCommitService gitCodeCommitService;

    @Autowired
    private ProjectService projectService;
    
    @Autowired
    private RepoConfigService repoConfigService;

    @Value("${app.init-data:false}")
    private boolean shouldInitData;

    @Value("${update.repos.cron:0 0 */1 * * ?}")
    private String updateCron;

    private final ProjectMapper projectMapper;
    private final DeveloperInfoMapper developerInfoMapper;
    private final PublishInfoMapper publishInfoMapper;
    private final XTSReportMapper xtsReportMapper;

    public DataInitService(ProjectMapper projectMapper, 
                         DeveloperInfoMapper developerInfoMapper,
                         PublishInfoMapper publishInfoMapper,
                         XTSReportMapper xtsReportMapper) {
        this.projectMapper = projectMapper;
        this.developerInfoMapper = developerInfoMapper;
        this.publishInfoMapper = publishInfoMapper;
        this.xtsReportMapper = xtsReportMapper;
    }

    @Override
    public void run(String... args) {
        try {
            if (shouldInitData && !isDataInitialized()) { 
                initializeData();
            }
            // 启动时立即执行一次更新
            updateRepositoryInfo();
        } catch (Exception e) {
            log.error("系统初始化失败", e);
        }
    }

    // 添加定时任务注解
    @Scheduled(cron = "${update.repos.cron:0 0 */1 * * ?}")
    public void scheduledUpdateRepositoryInfo() {
        log.info("开始定时更新仓库信息...");
        updateRepositoryInfo();
    }

    private void updateRepositoryInfo() {
        log.info("开始更新仓库信息...");
        try {
            List<Map<String, String>> repos = repoConfigService.loadRepoConfigs();
            if (repos.isEmpty()) {
                log.warn("没有找到需要更新的仓库配置");
                return;
            }
            
            log.info("找到 {} 个需要更新的仓库", repos.size());
            
            ExecutorService executor = Executors.newFixedThreadPool(3);
            try {
                log.info("开始并行更新仓库信息...");
                
                // 项目信息更新任务
                CompletableFuture<Boolean> projectUpdateFuture = CompletableFuture
                    .supplyAsync(() -> {
                        try {
                            log.info("开始执行项目信息更新任务");
                            projectService.updateProjectsFromRepos(repos);
                            return true;
                        } catch (Exception e) {
                            log.error("项目信息批量更新失败", e);
                            return false;
                        }
                    }, executor);

                // 提交信息和PR信息更新任务保持不变
                CompletableFuture<Boolean> commitUpdateFuture = CompletableFuture
                    .supplyAsync(() -> {
                        try {
                            log.info("开始执行发布信息更新任务");
                            updateAllCommitInfo(repos);
                            return true;
                        } catch (Exception e) {
                            log.error("提交信息批量更新失败", e);
                            return false;
                        }
                    }, executor);

                CompletableFuture<Boolean> prUpdateFuture = CompletableFuture
                    .supplyAsync(() -> {
                        try {
                            log.info("开始执行PR信息更新任务");
                            updateAllPRInfo(repos);
                            return true;
                        } catch (Exception e) {
                            log.error("PR信息批量更新失败", e);
                            return false;
                        }
                    }, executor);

                // 等待所有任务完成
                boolean projectUpdateResult = projectUpdateFuture.get(5, TimeUnit.MINUTES);
                boolean commitUpdateResult = commitUpdateFuture.get(5, TimeUnit.MINUTES);
                boolean prUpdateResult = prUpdateFuture.get(5, TimeUnit.MINUTES);

                log.info("所有更新任务执行完成 - 项目: {}, 提交: {}, PR: {}", 
                    projectUpdateResult ? "成功" : "失败",
                    commitUpdateResult ? "成功" : "失败",
                    prUpdateResult ? "成功" : "失败");
                
            } finally {
                executor.shutdown();
            }
        } catch (Exception e) {
            log.error("仓库信息更新失败", e);
        }
    }

    private void updateAllPRInfo(List<Map<String, String>> repos) {
        for (Map<String, String> repo : repos) {
            String owner = repo.get("owner");
            String name = repo.get("name");
            try {
                log.info("开始更新PR信息: {}/{}", owner, name);
                gitCodePRService.updateLatestPR(owner, name);
                log.info("PR信息更新完成: {}/{}", owner, name);
            } catch (Exception e) {
                log.error("更新PR信息失败: {}/{}", owner, name, e);
            }
        }
    }

    private void updateAllCommitInfo(List<Map<String, String>> repos) {
        for (Map<String, String> repo : repos) {
            String owner = repo.get("owner");
            String name = repo.get("name");
            String version = repo.get("version");
            try {
                log.info("开始更新提交信息: {}/{}", owner, name);
                gitCodeCommitService.updateCommitInfo(owner, name, version);
                log.info("提交信息更新完成: {}/{}", owner, name);
            } catch (Exception e) {
                log.error("更新提交信息失败: {}/{}", owner, name, e);
            }
        }
    }

    private void initializeData() {
        log.info("开始初始化基础数据...");
        try {
            initProjects();
            initDeveloperInfo();
            initPublisherInfo();
            initXTSReports();
            log.info("基础数据初始化完成");
        } catch (Exception e) {
            log.error("基础数据初始化失败", e);
            throw e;
        }
    }

    private boolean isDataInitialized() {
        // 检查是否存在任何记录
        return !projectMapper.findAll().isEmpty() ||
                !developerInfoMapper.findAll().isEmpty() ||
                !xtsReportMapper.findAll().isEmpty();
    }

    private void initProjects() {
        Project project = new Project();
        project.setOwner("admin");
        project.setName("Test Platform");
        project.setDescription("测试执行平台主项目");
        project.setGitUrl("http://github.com/test-platform");
        projectMapper.insert(project);
    }

    private void initDeveloperInfo() {
        DeveloperInfo info = new DeveloperInfo();
        info.setOwner("admin");
        info.setName("Test Platform");
        info.setDeveloper("张三");
        info.setPullRequest(123);
        info.setTitle("初级开发工程师");
        developerInfoMapper.insert(info);
    }

    private void initPublisherInfo() {
        PublishInfo info = new PublishInfo();
        info.setOwner("admin");
        info.setName("Test Platform");
        info.setPublisher("张三");
        info.setCommitId("1234567890");
        info.setTitle("初级开发工程师");
        publishInfoMapper.insert(info);
    }

    private void initXTSReports() {
        XTSReport report = new XTSReport();
        report.setOwner("admin");
        report.setName("Test Platform");
        report.setIterationVersion("v1.0.0");
        report.setApiVersion("API 2.0");
        report.setRunningResult("pass");
        xtsReportMapper.insert(report);
    }
}